/**
 * Copyright (c) 2008 ubermath
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met:
 *
 * * Redistributions of source code must retain the above copyright
 *   notice, this list of conditions and the following disclaimer.
 *
 * * Redistributions in binary form must reproduce the above copyright
 *   notice, this list of conditions and the following disclaimer in the
 *   documentation and/or other materials provided with the distribution.
 *
 * * Neither the name of 'ubermath' nor the names of its contributors 
 *   may be used to endorse or promote products derived from this software 
 *   without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * Created: Sep 6, 2008
 */

package com.googlecode.ubermath;

/**
 * @author Rebecca Hicks
 */
public class NumberString {
	private NumberString() {
	}
	public static String numberString(long i) {
		String out = "";
		boolean first = true;
		int count = 0;
		long t = i;
		
		if (i == 0) {
			out = "zero";
		} else {
			//find number of digits and create array of digits
			while (t > 0) {
				count++;
				t = t / 10;
			}
			t = i;
			long[] digits = new long[count];
			for (int j = 0; j < count; j++) {
				digits[j] = t % 10;
				t /= 10;
			}
			
			//iterate through each digit starting with the right-most digit
			for (int k = 0; k < count; k++) {
				String temp = "";
				//the first digit in each set of three (00x,00x,00x)
				if (k % 3 == 0) {
					//ignores zeroes in the ones place and special case "teen" numbers
					if (digits[k] != 0 && (k  == count - 1 || digits[k+1] != 1)) {
						temp += ones(digits[k]);
					//handles special case "teen" numbers
					} else if (digits[k] != 0 && digits[k+1] == 1) {
						temp += teens(digits[k]);
					}
					//adds the set name to the string if there are no zeroes in the set
					if (k >= 3 && (k - 3) % 9 == 0 && (k != 0 || digits[k+1] !=0 || digits[k+2] !=0)) {
						temp += " thousand";
					} else if (k >= 6 && (k - 6) % 9 == 0 && (k != 0 || digits[k+1] !=0 || digits[k+2] !=0)) {
						temp += " million";
					} else if (k >= 9 && (k - 9) % 9 == 0 && (k != 0 || digits[k+1] !=0 || digits[k+2] !=0)) {
						temp += " billion";
					}
				//the second digit in each set of three (0x0,0x0,0x0)
				} else if ((k - 1) % 3 == 0) {
					//ignores zeroes in the tens place
					if (digits[k] != 0) {
						//hyphenates double digit numbers appropriately (twenty-two, but not ten- or twelve-)
						if (digits[k-1] != 0) {
							temp += tens(digits[k]) + "-";
						} else {
							temp += tens(digits[k]);
						}
					}
				//the third digit in each set of three (x00,x00,x00)
				} else if ((k - 2) % 3 == 0) {
					//ignores zeroes in the hundreds place & adds 'hundred' to the string
					if (digits[k] != 0) {
						temp += ones(digits[k]) + " hundred";
					}
				}
				//adds a space between this digit and the previous digit if it isn't the first non-zero digit and isn't a hyphenated tens digit
				if (first) {
					if (!temp.equals("")) {
						first = false;
						out = temp;
					}
				} else {
					if ((((k - 1) % 3 == 0) && (digits[k] != 0) && (digits[k-1] != 0)) || temp.equals("")) {
						out = (temp + out);
					} else {
						out = (temp + " " + out);
					}
				}
				//skips the tens digit if the current digit is a special case "teen" number
				if (k % 3 == 0 && (k == count - 1 || (digits[k] != 0 && digits[k+1] ==1))) {
					k++;
				}
			}
		}
		return out;
	}
	
    private static String ones(long num) {
    	if (num==1) return "one";
    	else if (num==2) return "two";
    	else if (num==3) return "three";
    	else if (num==4) return "four";
    	else if (num==5) return "five";
    	else if (num==6) return "six";
    	else if (num==7) return "seven";
    	else if (num==8) return "eight";
    	else if (num==9) return "nine";
    	else return "";
    }
    private static String special(long num) {
    	if (num==3) return "thir";
    	else if (num==4) return "for";
    	else if (num==5) return "fif";
    	else if (num==8) return "eigh";
    	else return "";
    }
    private static String teens(long num) {
    	if (num==1) return "eleven";
    	else if (num==2) return "twelve";
    	else if (num==3 || num==5 || num==8) return special(num) + "teen";
    	else return ones(num) + "teen";
    }
    private static String tens(long num) {
    	if (num==1) return "ten";
    	else if (num==2) return "twenty";
    	else if (num==3 || num==4 || num==5 || num==8) return special(num) + "ty";
    	else return ones(num) + "ty";
    }
}
